package priv.lhy.ecm.basic.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import priv.lhy.common.abs.AbstractRequest;
import priv.lhy.ecm.basic.constants.BasicResponseCode;
import priv.lhy.ecm.basic.exception.BasicException;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * author: lihy
 * date: 2019/5/7 15:19
 * description: 防止重复提交AOP
 */
@Aspect
@Component
public class IsSubmitAspect {

    @Autowired
    private StringRedisTemplate redisTemplate;

    //redis过期时间
    @Value("${ecm.resubmit.timeout}")
    private String timeout;

    /**
     * 拦截规则：拦截标有priv.lhy.ecm.basic.annotation.IsSubmit的方法
     */
    @Pointcut("@annotation(priv.lhy.ecm.basic.annotation.ReSubmit)")
    public void reSubmitMethodPointcut() {
    }

    /**
     * 拦截器具体实现
     * @param point
     * @return
     */
    @Around("reSubmitMethodPointcut()")
    public Object Interceptor(ProceedingJoinPoint point) {
        //正在被通知的方法相关信息
        MethodSignature signature = (MethodSignature) point.getSignature();
        //获取被拦截的方法
        Method method = signature.getMethod();
        //获取被拦截的方法名
        String methodName = method.getName();
        //获取被拦截方法的参数
        Object[] args = point.getArgs();

        Object result = null;
        //redis的key
        String key = "resubmit:";
        AbstractRequest request = null;
        for (Object arg : args) {
            //获取请求
            if (arg instanceof AbstractRequest) {
                request = (AbstractRequest) arg;
                //组合redis的key
                key += request.getSessionId() + ":" + methodName;
                break;
            }
        }
        if (!redisTemplate.hasKey(key)) {
            //不存在说明未提交过，在redis中增加key，过期时间
            redisTemplate.opsForValue().set(key, "1", Long.parseLong(timeout), TimeUnit.MILLISECONDS);
            try {
                //执行被拦截方法
                result = point.proceed();
                //执行完成后删除redis中的key
                redisTemplate.delete(key);
                return result;
            } catch (Throwable throwable) {
                throw new BasicException(BasicResponseCode.SYSTEM_BUSY.getCode(), BasicResponseCode
                        .SYSTEM_BUSY.getMsg(), request);
            }
        } else {
            //存在说明已提交
            throw new BasicException(BasicResponseCode.SYS_RESUBMIT.getCode(), BasicResponseCode
                    .SYS_RESUBMIT.getMsg(), request);
        }

    }
}
